﻿using System;
using System.Diagnostics;

namespace JetBlack.Diagnostics
{
    /// <summary>
    /// Extension methods for <see cref="TraceSource"/> objects.
    /// </summary>
    public static class TraceSourceExtensions
    {
        private static void TraceEvent(this TraceSource traceSource, TraceEventType eventType, int id, string message)
        {
            if (traceSource.Switch.ShouldTrace(eventType))
                traceSource.TraceEvent(eventType, id, message);
        }

        /// <summary>
        /// Writes a verbose message.
        /// </summary>
        /// <param name="traceSource">The source object.</param>
        /// <param name="id">The event id.</param>
        /// <param name="message">The message to write.</param>
        public static void Verbose(this TraceSource traceSource, int id, string message)
        {
            TraceEvent(traceSource, TraceEventType.Verbose, id, message);
        }

        /// <summary>
        /// Write a verbose message.
        /// </summary>
        /// <param name="traceSource">The source object.</param>
        /// <param name="message">The message to write.</param>
        public static void Verbose(this TraceSource traceSource, string message)
        {
            TraceEvent(traceSource, TraceEventType.Verbose, 0, message);
        }

        /// <summary>
        /// Write a formatted verbose message.
        /// </summary>
        /// <param name="traceSource">The source object.</param>
        /// <param name="id">The event id.</param>
        /// <param name="format">The format string.</param>
        /// <param name="args">The args used by the format string.</param>
        public static void Verbose(this TraceSource traceSource, int id, string format, params object[] args)
        {
            TraceEvent(traceSource, TraceEventType.Verbose, id, string.Format(format, args));
        }

        /// <summary>
        /// Write a formatted verbose message.
        /// </summary>
        /// <param name="traceSource">The source object.</param>
        /// <param name="format">The format string.</param>
        /// <param name="args">The args used by the format string.</param>
        public static void Verbose(this TraceSource traceSource, string format, params object[] args)
        {
            TraceEvent(traceSource, TraceEventType.Verbose, 0, string.Format(format, args));
        }

        /// <summary>
        /// Write an information message.
        /// </summary>
        /// <param name="traceSource">The source object.</param>
        /// <param name="id">The event id.</param>
        /// <param name="message">The message to write.</param>
        public static void Information(this TraceSource traceSource, int id, string message)
        {
            TraceEvent(traceSource, TraceEventType.Information, id, message);
        }

        /// <summary>
        /// Write an information message.
        /// </summary>
        /// <param name="traceSource">The source object.</param>
        /// <param name="message">The message to write.</param>
        public static void Information(this TraceSource traceSource, string message)
        {
            TraceEvent(traceSource, TraceEventType.Information, 0, message);
        }

        /// <summary>
        /// Write a formatted information message.
        /// </summary>
        /// <param name="traceSource">The source object.</param>
        /// <param name="id">The event id.</param>
        /// <param name="format">The format string.</param>
        /// <param name="args">The args used by the format string.</param>
        public static void Information(this TraceSource traceSource, int id, string format, params object[] args)
        {
            TraceEvent(traceSource, TraceEventType.Information, id, string.Format(format, args));
        }

        /// <summary>
        /// Write a formatted information message.
        /// </summary>
        /// <param name="traceSource">The source object.</param>
        /// <param name="format">The format string.</param>
        /// <param name="args">The args used by the format string.</param>
        public static void Information(this TraceSource traceSource, string format, params object[] args)
        {
            TraceEvent(traceSource, TraceEventType.Information, 0, string.Format(format, args));
        }

        /// <summary>
        /// Write a warning message.
        /// </summary>
        /// <param name="traceSource">The source object.</param>
        /// <param name="id">The event id.</param>
        /// <param name="message">The message to write.</param>
        public static void Warning(this TraceSource traceSource, int id, string message)
        {
            TraceEvent(traceSource, TraceEventType.Warning, id, message);
        }

        /// <summary>
        /// Write a warning message.
        /// </summary>
        /// <param name="traceSource">The source object.</param>
        /// <param name="message">The message to write.</param>
        public static void Warning(this TraceSource traceSource, string message)
        {
            TraceEvent(traceSource, TraceEventType.Warning, 0, message);
        }

        /// <summary>
        /// Write a formatted warning message.
        /// </summary>
        /// <param name="traceSource">The source object.</param>
        /// <param name="id">The event id.</param>
        /// <param name="format">The format string.</param>
        /// <param name="args">The args used by the format string.</param>
        public static void Warning(this TraceSource traceSource, int id, string format, params object[] args)
        {
            TraceEvent(traceSource, TraceEventType.Warning, id, string.Format(format, args));
        }

        /// <summary>
        /// Write a formatted warning message.
        /// </summary>
        /// <param name="traceSource">The source object.</param>
        /// <param name="format">The format string.</param>
        /// <param name="args">The args used by the format string.</param>
        public static void Warning(this TraceSource traceSource, string format, params object[] args)
        {
            TraceEvent(traceSource, TraceEventType.Warning, 0, string.Format(format, args));
        }

        /// <summary>
        /// Writes an error message.
        /// </summary>
        /// <param name="traceSource">The source object.</param>
        /// <param name="id">The event id.</param>
        /// <param name="message">The message to write.</param>
        public static void Error(this TraceSource traceSource, int id, string message)
        {
            TraceEvent(traceSource, TraceEventType.Error, id, message);
        }

        /// <summary>
        /// Writes an error message.
        /// </summary>
        /// <param name="traceSource">The source object.</param>
        /// <param name="message">The message to write.</param>
        public static void Error(this TraceSource traceSource, string message)
        {
            TraceEvent(traceSource, TraceEventType.Error, 0, message);
        }

        /// <summary>
        /// Write a formatted error message.
        /// </summary>
        /// <param name="traceSource">The source object.</param>
        /// <param name="id">The event id.</param>
        /// <param name="format">The format string.</param>
        /// <param name="args">The args used by the format string.</param>
        public static void Error(this TraceSource traceSource, int id, string format, params object[] args)
        {
            TraceEvent(traceSource, TraceEventType.Error, id, string.Format(format, args));
        }

        /// <summary>
        /// Write a formatted error message.
        /// </summary>
        /// <param name="traceSource">The source object.</param>
        /// <param name="format">The format string.</param>
        /// <param name="args">The args used by the format string.</param>
        public static void Error(this TraceSource traceSource, string format, params object[] args)
        {
            TraceEvent(traceSource, TraceEventType.Error, 0, string.Format(format, args));
        }

        /// <summary>
        /// Writes an error message for an exception.
        /// </summary>
        /// <param name="traceSource">The source object.</param>
        /// <param name="exception">The exception.</param>
        public static void Error(this TraceSource traceSource, Exception exception)
        {
            TraceEvent(traceSource, TraceEventType.Error, 0, string.Format("{0}\n{1}", exception.Message, exception.StackTrace));
        }

        /// <summary>
        /// Writes an error message for an exception.
        /// </summary>
        /// <param name="traceSource">The source object.</param>
        /// <param name="message">The message.</param>
        /// <param name="exception">The exception.</param>
        public static void Error(this TraceSource traceSource, string message, Exception exception)
        {
            TraceEvent(traceSource, TraceEventType.Error, 0, string.Format("{0}\n{1}\n{2}", message, exception.Message, exception.StackTrace));
        }

        /// <summary>
        /// Writes a critical message.
        /// </summary>
        /// <param name="traceSource">The source object.</param>
        /// <param name="id">The event id.</param>
        /// <param name="message">The message to write.</param>
        public static void Critical(this TraceSource traceSource, int id, string message)
        {
            TraceEvent(traceSource, TraceEventType.Critical, id, message);
        }

        /// <summary>
        /// Writes a critical message.
        /// </summary>
        /// <param name="traceSource">The source object.</param>
        /// <param name="message">The message to write.</param>
        public static void Critical(this TraceSource traceSource, string message)
        {
            TraceEvent(traceSource, TraceEventType.Critical, 0, message);
        }

        /// <summary>
        /// Write a formatted critical message.
        /// </summary>
        /// <param name="traceSource">The source object.</param>
        /// <param name="id">The event id.</param>
        /// <param name="format">The format string.</param>
        /// <param name="args">The args used by the format string.</param>
        public static void Critical(this TraceSource traceSource, int id, string format, params object[] args)
        {
            TraceEvent(traceSource, TraceEventType.Critical, id, string.Format(format, args));
        }

        /// <summary>
        /// Write a formatted critical message.
        /// </summary>
        /// <param name="traceSource">The source object.</param>
        /// <param name="format">The format string.</param>
        /// <param name="args">The args used by the format string.</param>
        public static void Critical(this TraceSource traceSource, string format, params object[] args)
        {
            TraceEvent(traceSource, TraceEventType.Critical, 0, string.Format(format, args));
        }
    }
}
